using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

using NHibernate;

using Microsoft.Practices.CompositeUI;

using LibrErian.Interfaces.Data;
using LibrErian.Model;

namespace LibrErian.Data
{
	[Service(typeof(IDataManager))]
	public class NHibernateManager : IDataManager, IDisposable
	{
        private ISessionFactory factory;
		private ISession session;

        private NHibernateManager(ISession existingSession)
        {
            session = existingSession;
        }

        public NHibernateManager()
		{
			NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration();
			cfg.AddAssembly("LibrErian.Data");
			factory = cfg.BuildSessionFactory();
			session = factory.OpenSession();
		}

        public IDataManager GetDisconnectedManager()
        {
            ISession newSession = factory.OpenSession();
            newSession.FlushMode = FlushMode.Never;
            return new NHibernateManager(newSession);
        }
        
		public IList GetBooks(int libraryId)
		{
            IQuery query = session.CreateQuery("from Book book where LibraryId = ? ");
            query.SetInt32(0, libraryId);
            return query.List();
		}

        public IList GetBooksByGenre(int libraryId, int genreId)
        {
            IQuery query = session.CreateQuery("from Book book where ? in elements(book.Genres) and LibraryId = ?");
            query.SetInt32(0, genreId);
            query.SetInt32(1, libraryId);
            return query.List();
        }

        public IList GetBooksByAuthor(int libraryId, int auhtorId)
        {
            IQuery query = session.CreateQuery("from Book book where ? in elements(book.Authors) and LibraryId = ?");
            query.SetInt32(0, auhtorId);
            query.SetInt32(1, libraryId);
            return query.List();
        }

        public IList GetAuthors()
		{
            return session.CreateCriteria(typeof(Author)).List();
		}

        public IList GetGenres()
		{
            return session.CreateCriteria(typeof(Genre)).List();
		}

        public IList GetFormats()
        {
            return session.CreateCriteria(typeof(Format)).List();
        }

        public IList GetLibraries()
        {
            return session.CreateCriteria(typeof(Library)).List();
        }

        public Library GetLibraryById(int libraryId)
        {
            return (Library)session.Get(typeof(Library), libraryId);
        }
	
		public void SaveOrUpdate(object objectToSave)
		{
			ITransaction transaction = session.BeginTransaction();
			try
			{
				session.SaveOrUpdate(objectToSave);
				transaction.Commit();
			}
			catch
			{
				transaction.Rollback();
				throw;
			}
		}

        public void Delete(object objectToDelete)
        {
            ITransaction transaction = session.BeginTransaction();
            try
            {
                session.Delete(objectToDelete);
                transaction.Commit();
            }
            catch
            {
                transaction.Rollback();
                throw;
            }
        }

        public void Flush()
        {
            session.Flush();
        }

		public void CloseSession()
		{
			session.Close();
		}

        #region IDisposable Members

        public void Dispose()
        {
            CloseSession();
        }

        #endregion

    }
}
